package com.bocloud.cmp.dao.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import com.bocloud.cmp.dao.CloudServerDao;
import com.bocloud.cmp.entity.resource.CloudServer;
import com.bocloud.cmp.enums.RelationTarget;
import com.bocloud.cmp.enums.ResourceCatalog;
import com.bocloud.cmp.enums.ResourceCategory;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.MapTools;
import com.bocloud.database.core.intf.impl.JdbcGenericDao;
import com.bocloud.database.utils.SQLHelper;

/**
 * 云主机DAO接口实现类
 * 
 * @author dzg
 * @since 2016.09.12
 *
 */
@Repository("cloudServerDao")
public class CloudServerDaoImpl extends JdbcGenericDao<CloudServer, Long> implements CloudServerDao {

	@Override
	public CloudServer get(Long id) throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0 and id = :id";
		Map<String, Object> params = MapTools.simpleMap("id", id);
		List<CloudServer> list = this.list(CloudServer.class, sql, params);
		if (list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

	@Override
	public List<CloudServer> list(int page, int rows, List<Param> params, Map<String, String> sorter) throws Exception {
		String sql = "select a.*,b.name vendor_name,b.type vendor_type from cloud_server a left join cloud_vendor b on a.vendor_id = b.id where a.is_deleted = 0";
		sql = SQLHelper.buildRawSql(sql, page, rows, params, sorter, "a");
		Map<String, Object> paramMap = SQLHelper.getParam(params);
		return this.list(CloudServer.class, sql, paramMap);
	}

	@Override
	public List<SimpleBean> list(List<Param> params, Map<String, String> sorter) throws Exception {
		String sql = "select a.id,a.name from cloud_server a where a.is_deleted = 0";
		sql = SQLHelper.buildSql(sql, 1, Integer.MAX_VALUE, params, sorter, "a");
		Map<String, Object> paramMap = SQLHelper.getParam(params);
		List<CloudServer> vms = this.list(CloudServer.class, sql, paramMap);
		List<SimpleBean> beans = new ArrayList<>();
		for (CloudServer vm : vms) {
			beans.add(new SimpleBean(vm.getId(), vm.getName()));
		}
		return beans;
	}

	@Override
	public int count(List<Param> params) throws Exception {
		String sql = "select count(1) from cloud_server a where a.is_deleted = 0";
		sql = SQLHelper.buildRawSql(sql, params, null, "a");
		Map<String, Object> paramMap = SQLHelper.getParam(params);
		return this.countQuery(sql, paramMap).intValue();
	}

	@Override
	public boolean remove(Long id, Long userId) throws Exception {
		String sql = "update cloud_server set is_deleted = true,gmt_modify = :gmtModify,mender_id = :menderId where is_deleted = 0 and id = :id";
		Map<String, Object> params = MapTools.simpleMap("id", id);
		params.put("menderId", userId);
		params.put("gmtModify", new Date());
		return this.execute(sql, params) > 0;
	}

	/**
	 * 云主机的管理IP是否存在
	 * 
	 * @since V1.1 2016-09-13 modify by sxp 只检测是否存在，不需要查询出全部字段
	 */
	@Override
	public boolean exists(String name, Long vendorId) throws Exception {
		String sql = "select id from cloud_server a where a.is_deleted = 0 and a.name = :name and a.vendor_id = :vendorId";
		Map<String, Object> params = MapTools.simpleMap("name", name);
		params.put("vendorId", vendorId);
		List<CloudServer> list = this.list(CloudServer.class, sql, params);
		if (list.isEmpty()) {
			return false;
		}
		return true;
	}

	@Override
	public CloudServer get(String ip) throws Exception {
		String sql = "select * from cloud_server a where a.is_deleted = 0 and a.manager_ip = :ip";
		Map<String, Object> params = MapTools.simpleMap("ip", ip);
		List<CloudServer> list = this.list(CloudServer.class, sql, params);
		if (list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

	@Override
	public CloudServer getByName(String name) throws Exception {
		String sql = "select * from cloud_server where name = :name and is_deleted = 0";
		Map<String, Object> params = MapTools.simpleMap("name", name);
		List<CloudServer> list = this.list(CloudServer.class, sql, params);
		List<CloudServer> listNames = new ArrayList<>();
		for (CloudServer object : list) {
			listNames.add(object);
		}
		if (list.isEmpty()) {
			return null;
		}
		return listNames.get(0);
	}

	@Override
	public List<CloudServer> list() throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0";
		return this.list(CloudServer.class, sql);
	}

	@Override
	public CloudServer getByUUID(String uuid) throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0 and uuid = :uuid";
		Map<String, Object> params = MapTools.simpleMap("uuid", uuid);
		List<CloudServer> list = this.list(CloudServer.class, sql, params);
		if (list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

	@Override
	public List<CloudServer> list(Long userId, Date newDate) throws Exception {
		String sql = "select cs.*,cv.name vendor_name from cloud_server cs,resource r,object_relation rr,cloud_vendor cv where cs.is_deleted = 0 and cs.id = r.target and r.is_deleted = 0 and r.category = :category and r.catalog = :catalog and r.id = rr.res_id and rr.target= :target and rr.category =:rr_category and cs.vendor_id = cv.id and (isnull (cs.expired_time) or (cs.expired_time >= :newDate and cs.gmt_create<=:newDate))";
		Map<String, Object> paramMap = MapTools.simpleMap("category", ResourceCategory.Computer.name());
		paramMap.put("catalog", ResourceCatalog.LOGICAL.name());
		paramMap.put("target", userId);
		paramMap.put("newDate", newDate);
		paramMap.put("rr_category", RelationTarget.USER.name());
		return this.list(CloudServer.class, sql, paramMap);
	}

	@Override
	public CloudServer query(Long id) throws Exception {
		String sql = "select a.*,b.name vendor_name from cloud_server a left join cloud_vendor b on a.vendor_id = b.id where a.is_deleted = 0 and a.id = :id";
		Map<String, Object> params = MapTools.simpleMap(Common.ID, id);
		List<CloudServer> list = this.list(CloudServer.class, sql, params);
		if (list.isEmpty()) {
			return null;
		} else {
			return list.get(0);
		}
	}

	@Override
	public List<CloudServer> queryAll() throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0 and is_template = 0";
		return this.list(CloudServer.class, sql);
	}

	@Override
	public List<CloudServer> listByVendorId(Long vendorId) throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0 and vendor_id = :vendorId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		return this.list(CloudServer.class, sql, params);
	}

	@Override
	public List<CloudServer> listByHid(Long hostId) throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0 and host_id = :hostId";
		Map<String, Object> params = MapTools.simpleMap("hostId", hostId);
		return this.list(CloudServer.class, sql, params);
	}

	@Override
	public List<CloudServer> listByVid(Long vendorId) throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0 and vendor_id = :vendorId and (is_template = 0 or is_template is null)";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		return this.list(CloudServer.class, sql, params);
	}

	@Override
	public boolean removeByVid(Long vendorId, Long userId) throws Exception {
		String sql = "update cloud_server set is_deleted = true,gmt_modify = :gmtModify,mender_id = :menderId where is_deleted = 0 and vendor_id = :vendorId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put("menderId", userId);
		params.put("gmtModify", new Date());
		return this.execute(sql, params) > 0;
	}

	@Override
	public CloudServer getByServerId(String serverId) throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0 and server_id = :serverId";
		Map<String, Object> params = MapTools.simpleMap("serverId", serverId);
		List<CloudServer> list = this.list(CloudServer.class, sql, params);
		CloudServer server = new CloudServer();
		if (!list.isEmpty()) {
			server = list.get(0);
		}
		return server;
	}

	@Override
	public List<CloudServer> list(Long vendorId, String networkId) throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0 and vendor_id = :vendorId and network_id = :networkId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put("networkId", networkId);
		return this.list(CloudServer.class, sql, params);
	}

	@Override
	public List<CloudServer> listByFid(Long vendorId, String flavorId) throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0 and vendor_id = :vendorId and flavor_id = :flavorId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put("flavorId", flavorId);
		return this.list(CloudServer.class, sql, params);
	}

	@Override
	public List<CloudServer> listByIid(Long vendorId, String imageId) throws Exception {
		String sql = "select * from cloud_server where is_deleted = 0 and vendor_id = :vendorId and image_id = :imageId";
		Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
		params.put("imageId", imageId);
		return this.list(CloudServer.class, sql, params);
	}

	@Override
	public List<Map<String, String>> getAll4Snmp() throws Exception {
		String sql = "select uuid,manager_ip from cloud_server where is_deleted = 0";
		List<CloudServer> vms = this.list(CloudServer.class, sql);

		List<Map<String, String>> result = new ArrayList<>();
		Map<String, String> map;
		String ip;

		for (CloudServer vm : vms) {
			ip = vm.getManagerIp();
			if (StringUtils.isEmpty(ip)) {
				continue;
			}

			map = new HashMap<>();
			map.put("uuid", vm.getUuid());
			map.put("ip", ip);
			result.add(map);
		}

		return result;
	}

	@Override
	public boolean removeByHost(Long hostId, Long userId) throws Exception {
		String sql = "update cloud_server set is_deleted = true,gmt_modify = :gmtModify,mender_id = :menderId where is_deleted = 0 and host_id = :hostId";
		Map<String, Object> params = MapTools.simpleMap("hostId", hostId);
		params.put("menderId", userId);
		params.put("gmtModify", new Date());
		return this.execute(sql, params) > 0;
	}

	@Override
	public List<CloudServer> listvmByvhost(long venderId, String hostName) throws Exception {
		String sql = "SELECT a.* FROM  cloud_server a where a.is_deleted = 0 and a.vendor_id = :venderId and a.host_name = :hostName";
		Map<String, Object> params = MapTools.simpleMap("venderId", venderId);
		params.put("hostName", hostName);
		return this.list(CloudServer.class, sql, params);
	}

	@Override
	public int count(List<Param> params, String type) throws Exception {
		String sql = "select count(1) from cloud_server a,cloud_vendor b where a.is_deleted = 0 and a.vendor_id = b.id";
		if (!StringUtils.isEmpty(type)) {
			sql += " and b.type = '" + type + "'";
		}
		sql = SQLHelper.buildRawSql(sql, params, null, "a");
		Map<String, Object> paramMap = SQLHelper.getParam(params);
		return this.countQuery(sql, paramMap).intValue();
	}

	@Override
	public boolean updateStatusByHost(Long hostId, String status, Long userId, String original) throws Exception {
		String sql = "update cloud_server set status = :status,gmt_modify = :gmtModify,mender_id = :menderId where is_deleted = 0 and host_id = :hostId and status = :original";
		Map<String, Object> params = MapTools.simpleMap("hostId", hostId);
		params.put("menderId", userId);
		params.put("gmtModify", new Date());
		params.put("status", status);
		params.put("original", original);
		return this.execute(sql, params) > 0;
	}

	@Override
	public List<CloudServer> listByStore(Long storeId) throws Exception {
		String sql = "select a.* from cloud_server a,store_host b where a.is_deleted = 0 and a.is_template = false and a.id = b.vhost_id and b.category = 'VM' and b.store_id = :storeId";
		Map<String, Object> params = MapTools.simpleMap("storeId", storeId);
		return this.list(CloudServer.class, sql, params);
	}

	@Override
	public List<CloudServer> listByNetwork(Long networkId) throws Exception {
		String sql = "select a.* from cloud_server a,network_host b where a.is_deleted = 0 and a.is_template = false and a.id = b.vhost_id and b.category = 'VM' and b.network_id = :networkId";
		Map<String, Object> params = MapTools.simpleMap("networkId", networkId);
		return this.list(CloudServer.class, sql, params);
	}

	@Override
	public List<CloudServer> listByName(String name, Long vendorId) throws Exception {
		String sql = "select * from cloud_server a where a.is_deleted = 0 and a.name = :name and a.vendor_id = :vendorId";
		Map<String, Object> params = MapTools.simpleMap("name", name);
		params.put("vendorId", vendorId);
		List<CloudServer> list = this.list(CloudServer.class, sql, params);
		return list;
	}

}
